package com.foogui.java8.stream;

import com.foogui.java8.utils.ListUtil;
import com.foogui.java8.vo.Dish;
import com.foogui.java8.vo.Trader;
import com.foogui.java8.vo.Transaction;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo {
    /**
     * 创建流
     */
    @Test
    public void createStream() {
        Stream<String> stream = Stream.of("a", "b", "c", "d", "e", "f");
    }

    @Test
    public void test01() {
        List<Dish> menu = ListUtil.createDishList();
        menu.stream().filter(ele -> ele.getCalories() < 400)
                .sorted(Comparator.comparing(Dish::getCalories))
                //map 将元素转换成其他形式或提取信息
                .map(Dish::getName)
                .distinct()
                .limit(3)
                .collect(Collectors.toList())
                .forEach(System.out::println);
    }

    //查找和匹配 allMatch、anyMatch、noneMatch、findFirst和findAny
    @Test
    public void test02() {
        List<Dish> menu = ListUtil.createDishList();
        if (menu.stream().anyMatch(Dish::isVegetarian)) {
            System.out.println("菜单里存在蔬菜");
        }
        // Optional避免find为null的情况
        Optional<Dish> first = menu.stream().filter(Dish::isVegetarian)
                .findFirst();
        first.ifPresent(ele -> System.out.println(ele.getName()));

    }

    //reduce求和
    @Test
    public void test03() {
        List<Dish> menu = ListUtil.createDishList();
        Integer sum = menu.stream().map(Dish::getCalories)
                .reduce(0, Integer::sum);
        System.out.println(sum);
        //用map和reduce方法数一数流中有多少个菜
        Integer reduce = menu.stream().map(dish -> 1)
                .reduce(0, Integer::sum);

        System.out.println(reduce);
    }

    //交易员和交易练习
    @Test
    public void test04() {
        List<Transaction> list = ListUtil.createTransactionList();
        // 找出 2011 年发生的所有交易，并按交易额排序（从低到高）
        list.stream().filter(transaction -> transaction.getYear() == 2011)
                .sorted(Comparator.comparing(Transaction::getValue))
                .collect(Collectors.toList())
                .forEach(System.out::println);
        // 交易员都在哪些不同的城市工作过？
        list.stream().map(Transaction::getTrader)
                .map(Trader::getCity)
                .collect(Collectors.toSet())
                .forEach(System.out::println);
        // 查找所有来自于剑桥的交易员，并按姓名排序。
        list.stream().map(Transaction::getTrader)
                .filter(trader -> trader.getCity().equals("Cambridge"))
                .sorted(Comparator.comparing(Trader::getName))
                .forEach(System.out::println);
        // 返回所有交易员的姓名字符串合并，按字母顺序排序。
        String res = list.stream().map(transaction -> transaction.getTrader().getName())
                .sorted()
//                .reduce("", (a, b) -> a + b);
                .collect(Collectors.joining());     //效率比reduce高
        System.out.println(res);
        // 有没有交易员是在米兰工作的？
        boolean isMilan = list.stream().anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"));
        System.out.println(isMilan);

        // 打印生活在剑桥的交易员的所有总交易额。
        Integer sum = list.stream().filter(transaction -> transaction.getTrader().getCity().equals("Milan"))
                .map(Transaction::getValue)
                .reduce(0, Integer::sum);
        System.out.println(sum);
        // 所有交易中，最高的交易额是多少？
        Optional<Integer> max = list.stream().map(Transaction::getValue)
                .reduce(Integer::max);
        System.out.println(max);
        // 找到交易额最小的交易。
        Optional<Transaction> reduce = list.stream().reduce((a, b) -> a.getValue() < b.getValue() ? a : b);
        System.out.println(reduce);
        Optional<Transaction> min = list.stream().min(Comparator.comparing(Transaction::getValue));
        System.out.println(min);

    }

    /**
     * 筛选value为奇数的map
     */
    @Test
    public void test05() {
        HashMap<String, Integer> map = new HashMap<>();
        HashMap<String, Integer> res = new HashMap<>();
        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);
        map.put("4", 4);
        map.put("5", 5);
        Map<String, Integer> collect = map.entrySet().stream()
                .filter(ele -> ele.getValue() % 2 != 0)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        System.out.println(collect);
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        map.forEach((a,b)->{
            if (b%2!=0){
                res.put(a,b);
            }
        } );
        System.out.println(res);

    }
    @Test
    public void testFlatMap() {
        List<Integer> numbers1 = Arrays.asList(1, 2, 3);
        List<Integer> numbers2 = Arrays.asList(3, 4);
        List<String> collect = numbers1.stream()
                .flatMap(i -> numbers2.stream().map((j -> "(" + i + "," + j + ")")))
                .collect(Collectors.toList());
        System.out.println(collect);
    }
}
